在古早時代,如果製作遊戲時要使用動畫,有時候一張一張的圖片讀取進來,電腦的效能無法支撐.所以在比較爛的電腦上就會一卡一卡的不滑順.這個時候就會改為使用滑動視窗動畫來呈現.
這個作法是這樣的,把所有動畫都放在一張大圖上面,但是用一個小視窗當成呈現的區塊.而其他區塊就不呈現在使用者面前.當要更新動畫內容的時候,不用重新載入圖片,而是只要移動小視窗,這樣就會自行更新呈現的樣子,完成動畫效果.

(比如說上面這張圖要展示爆炸的動畫,只要用穩定的速度從(2,2)格移動到(2,5)格,看起來就有那麼一回事)
而滑動視窗演算法也像是這樣,我們維護一個不停移動的視窗,然後更新答案
這個演算法的思考大概如下
fun windowAlgo(s:Array<T>){
    var left = 0
    var right = 0
    while(right<s.size){
        //增大視窗
        window.add(s[right])
        right++
        while ( window needs shrink){//檢查需要縮小視窗
            //縮小視窗
            window.remove(s[left])
            left++
        }
    }
}
這種演算法的時間複雜度是O(N),比字串暴力演算有效的多.
其實困難的不是演算法的思路,而是細節很多.例如如何讓視窗增加元素,如何縮小視窗,在滑動的哪個階段更新結果.即使明白這些細節,也很容易有bug,而且bug還很難找.
所以我們將思考擴寫成框架
fun slidingWindow(s: String, t: String) {
    val need: HashMap<Char, Int> = HashMap()
    val window: HashMap<Char, Int> = HashMap()
    t.forEach { need[it] = 1 }
    
    var left = 0
    var right = 0
    var valid = 0
    while(right<s.length){
        //c是即將移入視窗的字元
        val c = s[right]
        //右移視窗
        right++
        //進行視窗內的一系列更新
        ...
        while(whindow need shrink){
            //d 是即將移出視窗的字元
            val d = s[left]
            //左移視窗
            left++
            //進行視窗內的一系列更新
            ...
        }
    }
}
其中...代表要更新資料的地方,根據題目填入邏輯即可.而且這兩處的操作,會分別是右邊進入以及左邊移除的操作,而之後會發現這兩者完全相同.